package run.iget.admin.system.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;

import run.iget.admin.system.bean.RoleDepartmentDTO;
import run.iget.admin.system.entity.AdministratorDepartment;
import run.iget.admin.system.entity.Department;
import run.iget.admin.system.entity.RoleDepartment;
import run.iget.admin.system.entity.table.DepartmentTableDef;
import run.iget.admin.system.entity.table.RoleDepartmentTableDef;
import run.iget.admin.system.mapper.DepartmentMapper;
import run.iget.admin.system.service.AdministratorDepartmentService;
import run.iget.admin.system.service.DepartmentRoleService;
import run.iget.admin.system.service.DepartmentService;
import run.iget.framework.common.enums.BaseStatusEnum;
import run.iget.framework.common.enums.YesOrNoEnum;
import run.iget.framework.common.util.ExceptionThrowUtils;
import run.iget.framework.common.util.TreeUtils;

/**
 * <p>
 * 系统部门 服务实现类
 * </p>
 *
 * @author 大周
 * @since 2022-02-07
 */
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {

    @Resource
    private DepartmentRoleService          departmentRoleService;

    @Resource
    private AdministratorDepartmentService administratorDepartmentService;

    @Override
    public boolean save(Department entity) {
        entity.setId(null);
        // 父节点的孩子数量+1
        QueryWrapper queryWrapper = QueryWrapper.create().where(DepartmentTableDef.DEPARTMENT.ID.eq(entity.getPid()));
        this.mapper.updateNumberAddByQuery(DepartmentTableDef.DEPARTMENT.CHILDREN_NUM, 1, queryWrapper);

        Department parent = this.getById(entity.getPid());
        // 节点的code = 父节点code + 孩子数量 有并发问题导致code不唯一，后续改为其他实现方式
        String code = parent.getCode() + parent.getChildrenNum();
        entity.setCode(code);
        entity.setDeletable(YesOrNoEnum.Y.getCode());
        return super.save(entity);
    }

    @Override
    public boolean updateById(Department entity) {
        String code = entity.getCode();
        entity.setPid(null);
        entity.setCode(null);
        entity.setDeletable(null);
        boolean result = super.updateById(entity);

        // 如果是禁用，则将子节点数据都禁用
        if (BaseStatusEnum.isDisable(entity.getStatus())) {
            Department update = new Department();
            update.setStatus(BaseStatusEnum.DISABLE.getCode());
            QueryWrapper queryWrapper = QueryWrapper.create().where(DepartmentTableDef.DEPARTMENT.CODE.likeRight(code));
            this.mapper.updateByQuery(update, queryWrapper);
        }
        return result;
    }

    @Override
    public List<Department> tree(Department department) {
        List<Department> departmentList = this.list(QueryWrapper.create(department));
        List<Department> tree = TreeUtils.build(departmentList);
        return tree;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveOrUpdate(RoleDepartmentDTO roleDepartmentDTO) {
        if (roleDepartmentDTO.getId() == null) {
            this.save(roleDepartmentDTO);
        } else {
            this.updateById(roleDepartmentDTO);
        }
    }

    @Override
    public List<Long> queryRelationRoleIds(Long id) {
        List<RoleDepartment> list = departmentRoleService
                .list(RoleDepartmentTableDef.ROLE_DEPARTMENT.DEPARTMENT_ID.eq(id));
        return Optional.ofNullable(list).orElse(new ArrayList<>(0)).stream().map(RoleDepartment::getRoleId)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void delete(Department department) {
        AdministratorDepartment administratorDepartment = new AdministratorDepartment();
        administratorDepartment.setDepartmentId(department.getId());
        List<AdministratorDepartment> list = administratorDepartmentService.query(administratorDepartment);
        ExceptionThrowUtils.ofEmpty(list, "部门下面有用户，不可删除");
        // 父节点的孩子数量-1
        QueryWrapper queryWrapper = QueryWrapper.create()
                .where(DepartmentTableDef.DEPARTMENT.ID.eq(department.getPid()));
        this.mapper.updateNumberAddByQuery(DepartmentTableDef.DEPARTMENT.CHILDREN_NUM, -1, queryWrapper);

        // 构建删除条件
        queryWrapper = QueryWrapper.create().where(DepartmentTableDef.DEPARTMENT.ID.eq(department.getId()))
                .and(DepartmentTableDef.DEPARTMENT.DELETABLE.eq(YesOrNoEnum.Y.getCode()));
        this.remove(queryWrapper);
    }
}
